#include <CoOS.h>
#include <ff.h>
#include <Config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <system_stm32f10x.h>
#include <stm32f10x_spi.h>
#include <stm32f10x_tim.h>
#include <misc.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_usart.h>
#include <LCD_driver.h>
#include <USART_TERM.h>
#include <DAC_STM32.h>
#include <Fat_Func.h>

#include <ParseString.h>
#include <Command.h>
#include <VS1003_Audio_Decoder.h>
#include <Keypad4x4.h>
#include <LED_driver.h>
#include <ADC_STM32.h>

extern USART_TypeDef* USARTx;
extern CONNECT_type FLAG_CONNECT_TYPE;

extern int OUTx;
extern unsigned int flag_export_usart;
extern unsigned int flag_adc_alarm_maxmin;

//-CoOS variable--------------------------------------------------------------
// define tasks size
#define task_browse_sdcard_size 	1024*2
#define task_get_usartTerm_size 	1024
#define task_led_blinky_size 		48
#define task_generate_dac_size		256
#define task_write_sdcard_size 		128
#define task_adc_convert_size		256
#define task_keypad_size			256
#define task_lcd_menu_size			512
// define task priority
#define task_browse_sdcard_pri 		2
#define task_get_usartTerm_pri 		1
#define task_led_blinky_pri 		2
#define task_generate_dac_pri		2
#define task_write_sdcard_pri			2
#define task_adc_convert_pri		2
#define task_keypad_pri				1
#define task_lcd_menu_pri			3
// task ID
OS_TID task_browse_sdcard_id;
OS_TID task_get_usartTerm_id;
OS_TID task_led_blinky_id;
OS_TID task_generate_dac_id;
OS_TID task_write_sdcard_id;
OS_TID task_adc_convert_id;
OS_TID task_keypad_id;
OS_TID task_lcd_menu_id;
// task stack
OS_STK task_browse_sdcard_stk[task_browse_sdcard_size];
OS_STK task_get_usartTerm_stk[task_get_usartTerm_size];
OS_STK task_led_blinky_stk[task_led_blinky_size];
OS_STK task_generate_dac_stk[task_generate_dac_size];
OS_STK task_write_sdcard_stk[task_write_sdcard_size];
OS_STK task_adc_convert_stk[task_adc_convert_size];
OS_STK task_keypad_stk[task_keypad_size];
OS_STK task_lcd_menu_stk[task_lcd_menu_size];
// mutex ID
OS_MutexID task_browse_sdcard_mutex;
OS_MutexID task_get_usartTerm_mutex;
OS_MutexID task_generate_dac_mutex;
OS_MutexID task_write_sdcard_mutex;
OS_MutexID task_led_blinky_mutex;
OS_MutexID task_adc_convert_mutex;
OS_MutexID task_keypad_mutex;
OS_MutexID task_lcd_menu_mutex;
// Flag ID

//-task declare--------------------------------------------------------------
void task_get_usartTerm(void* pdata);
void task_browse_sdcard(void* pdata);
void task_generate_dac(void* pdata);
void task_led_blinky(void* pdata);
void task_write_sdcard(void* pdata);
void task_adc_convert(void* pdata);
void task_keypad(void* pdata);
void task_lcd_menu(void* pdata);
//-define function--------------------------------------------------------------
#define create_task_browse_sdcard \
	CoCreateTask(task_browse_sdcard, (void *)0,\
			task_browse_sdcard_pri,\
			&task_browse_sdcard_stk[task_browse_sdcard_size - 1],\
			task_browse_sdcard_size)
#define create_task_get_usartTerm \
	CoCreateTask(task_get_usartTerm,(void *)0,\
			task_get_usartTerm_pri,\
			&task_get_usartTerm_stk[task_get_usartTerm_size - 1],\
			task_get_usartTerm_size)
#define create_task_led_blinky \
	CoCreateTask(task_led_blinky,(void *)0,\
			task_led_blinky_pri,\
			&task_led_blinky_stk[task_led_blinky_size - 1],\
			task_led_blinky_size)
#define create_task_generate_dac \
	CoCreateTask(task_generate_dac,(void *)0,\
			task_generate_dac_pri,\
			&task_generate_dac_stk[task_generate_dac_size - 1],\
			task_generate_dac_size)
#define create_task_write_sdcard \
	CoCreateTask(task_write_sdcard,(void *)0,\
			task_write_sdcard_pri,\
			&task_write_sdcard_stk[task_write_sdcard_size - 1],\
			task_write_sdcard_size)
#define create_task_adc_convert \
	CoCreateTask(task_adc_convert,(void *)0,\
			task_adc_convert_pri,\
			&task_adc_convert_stk[task_adc_convert_size - 1],\
			task_adc_convert_size)
#define create_task_keypad \
	CoCreateTask(task_keypad,(void *)0,\
			task_keypad_pri,\
			&task_keypad_stk[task_keypad_size - 1],\
			task_keypad_size)
#define create_task_lcd_menu \
	CoCreateTask(task_lcd_menu,(void *)0,\
			task_lcd_menu_pri,\
			&task_lcd_menu_stk[task_lcd_menu_size - 1],\
			task_lcd_menu_size)
//-function for task using--------------------------------------------------------------
unsigned int Keypad_Set_Value(unsigned int Min, unsigned int Max, char *unit);
//-global variables--------------------------------------------------------------
//menu list on LCD
char Menu_led[9][20] = { "SHR", "SHL", "Inc L->R", "Inc R->L", "Dec L->R",
		"Dec R->L", "IncDec L->R", "IncDec R->L", "" };
char Menu_adc[7][20] = { "ADC read", "set alarm min", "get alarm min",
		"set alarm max", "get alarm max", "active alarm", "" };
char Menu_dac[6][20] = { "gen const", "gen sine", "gen square",
		"gen triangular", "gen square custom", "" };
FILINFO List_file[100];
static WAV_INFO WAV_info_to_read;
char file_content_to_lcd[2][20];
char filename_open[16];
char folder_name[12];
char Path_folder[128] = "";
char data_write[512] ="";
MODESEL Mode_Sel = file_mode;
CMDRES CMD_index = error_cmd;
unsigned int dac_valA = 0, dac_valB = 0;
unsigned int led_delay = 0;
unsigned int adc_val = 0;
lcd_menu_level lcd_menu_lvl = root_level;
unsigned int lcd_menu_index = 0;
//-user flags--------------------------------------------------------------
unsigned int flag_browse = 0;
unsigned int flag_dac_gen = 0;
unsigned int flag_write_sdcard = 0;
unsigned int flag_led_blinky = 0;
unsigned int flag_adc_convert = 0;
unsigned int flag_lcd_display = 0;
unsigned int flag_keypad_get = 0;
//only for working with keypad + LCD
unsigned int flag_open_file = 0;
//---------------------------------------------------------------
/*
 *
 */
void task_lcd_menu(void* pdata) {
	while (1) {
		CoEnterMutexSection(task_lcd_menu_mutex);
		if (flag_lcd_display == 1) {
			if (lcd_menu_lvl == root_level) {
				if (Mode_Sel == adc_mode) {
					LCD_ClearLine(0);
					OUTPUT_LCD;
					puts("->");
					puts(Menu_adc[lcd_menu_index]);
					LCD_ClearLine(1);
					OUTPUT_LCD;
					puts(Menu_adc[lcd_menu_index + 1]);
				} else if (Mode_Sel == dac_mode) {
					LCD_ClearLine(0);
					OUTPUT_LCD;
					puts("->");
					puts(Menu_dac[lcd_menu_index]);
					LCD_ClearLine(1);
					OUTPUT_LCD;
					puts(Menu_dac[lcd_menu_index + 1]);
				} else if (Mode_Sel == led_mode) {
					LCD_ClearLine(0);
					OUTPUT_LCD;
					puts("->");
					puts(Menu_led[lcd_menu_index]);
					LCD_ClearLine(1);
					OUTPUT_LCD;
					puts(Menu_led[lcd_menu_index + 1]);
				} else if (Mode_Sel == file_mode) {
					if (CMD_index == file_dir_cmd) {
						strcpy(filename_open, List_file[lcd_menu_index].fname);
						LCD_ClearLine(0);
						OUTPUT_LCD;
						printf("->%s", List_file[lcd_menu_index].fname);
						LCD_ClearLine(1);
						OUTPUT_LCD;
						puts(List_file[lcd_menu_index + 1].fname);
					} else if (CMD_index == file_open_text_cmd) {
						LCD_ClearLine(0);
						OUTPUT_LCD;
						puts(file_content_to_lcd[0]);
						LCD_ClearLine(1);
						OUTPUT_LCD;
						puts(file_content_to_lcd[1]);
					}
				}
			}
			flag_lcd_display = 0;
		}
		CoLeaveMutexSection(task_lcd_menu_mutex);
		CoTickDelay(1);
	}
}

/*
 *
 */
void task_write_sdcard(void* pdata) {
	unsigned long ofs = 0;
	while (1) {
		CoEnterMutexSection(task_write_sdcard_mutex);
		if (CMD_index == file_create_cmd) {
			if(strlen(data_write) >= 512/2)
			{
				ofs = ofs + WriteFile(filename_open, str_tmp, ofs);
			}
		}
		CoLeaveMutexSection(task_write_sdcard_mutex);
		CoTickDelay(1);
	}
}

/*
 *
 */
void task_generate_dac(void* pdata) {
	DAC1_Configuration();
	OUTPUT_USARTTerm;
	puts("DAC1_Configuration\r\n");
	while (1) {
		CoEnterMutexSection(task_generate_dac_mutex);
		if (flag_dac_gen == 1) {
			if (CMD_index == dac_const_cmd) {
				DAC1_generate_const(dac_valA);
				OUTPUT_USARTTerm;
				puts("DAC generate const DONE\r\n");
				flag_dac_gen = 0;
			} else if (CMD_index == dac_sine_cmd) {
				DAC1_generate_sine(dac_valA);
				OUTPUT_USARTTerm;
				puts("DAC generate sine DONE\r\n");
				flag_dac_gen = 0;
			} else if (CMD_index == dac_triangular_cmd) {
				DAC1_generate_triangular(dac_valA);
				OUTPUT_USARTTerm;
				puts("DAC generate triangular DONE\r\n");
				flag_dac_gen = 0;
			} else if (CMD_index == dac_square_cmd) {
				DAC1_generate_square(dac_valA);
				OUTPUT_USARTTerm;
				puts("DAC generate square DONE\r\n");
				flag_dac_gen = 0;
			} else if (CMD_index == dac_squarecustom_cmd) {
				DAC1_generate_squarecustom(dac_valA, dac_valB);
				OUTPUT_USARTTerm;
				puts("DAC generate square custom DONE\r\n");
				flag_dac_gen = 0;
			}
		}
		CoLeaveMutexSection(task_generate_dac_mutex);
		CoTickDelay(1);
	}
}

/*
 *
 */
void task_adc_convert(void* pdata) {
	unsigned int adc_res = 0;
	ADC1_configuration();
	OUTPUT_USARTTerm;
	puts("ADC1_configuration\r\n");
	timer_ADC_config();
	OUTPUT_USARTTerm;
	puts("timer_ADC_config\r\n");
	while (1) {
		CoEnterMutexSection(task_adc_convert_mutex);
		if (flag_adc_alarm_maxmin == 1) {
			LCD_ClearLine(1);
			OUTPUT_LCD;
			puts("ADC ALARM MIN");
			flag_adc_alarm_maxmin = 0;
		} else if (flag_adc_alarm_maxmin == 2) {
			LCD_ClearLine(1);
			OUTPUT_LCD;
			puts("ADC ALARM MAX");
			flag_adc_alarm_maxmin = 0;
		}
		if (flag_adc_convert == 1) {
			if (CMD_index == adc_read_cmd) {
				adc_res = ADC1_ReadInput();
				OUTPUT_USARTTerm;
				puts("ADC result: ");
				flag_export_usart = 1;
				printf("%u", adc_res);
				flag_export_usart = 0;
				puts(" %\r\n");
				flag_adc_convert = 0;
				LCD_ClearLine(1);
				OUTPUT_LCD;
				printf("%u %%", adc_res);
			} else if (CMD_index == adc_set_alarm_max_cmd) {
				ADC1_Set_alarm_level(1, adc_val);
				flag_adc_convert = 0;
			} else if (CMD_index == adc_set_alarm_min_cmd) {
				ADC1_Set_alarm_level(0, adc_val);
				flag_adc_convert = 0;
			} else if (CMD_index == adc_get_alarm_max_cmd) {
				adc_res = ADC1_Get_alarm_level(1);
				OUTPUT_USARTTerm;
				puts("ADC alarm max is: ");
				flag_export_usart = 1;
				printf("%u", adc_res);
				flag_export_usart = 0;
				puts(" %\r\n");
				flag_adc_convert = 0;
				LCD_ClearLine(1);
				OUTPUT_LCD;
				printf("%u %%", adc_res);
			} else if (CMD_index == adc_get_alarm_min_cmd) {
				adc_res = ADC1_Get_alarm_level(0);
				OUTPUT_USARTTerm;
				printf("ADC alarm min is: ");
				flag_export_usart = 1;
				printf("%u", adc_res);
				flag_export_usart = 0;
				puts(" %\r\n");
				flag_adc_convert = 0;
				LCD_ClearLine(1);
				OUTPUT_LCD;
				printf("%u %%", adc_res);
			} else if (CMD_index == adc_act_alarm_cmd) {
				ADC1_active_Alarm(adc_val);
				flag_adc_convert = 0;
			}
		}
		CoLeaveMutexSection(task_adc_convert_mutex);
		CoTickDelay(1);
	}
}

/****************************************************************
 * task to browse file in SD card
 *
 ****************************************************************/
void task_browse_sdcard(void* pdata) {
	while (1) {
		CoEnterMutexSection(task_browse_sdcard_mutex);
		if (flag_browse == 1) {
			if (CMD_index == file_dir_cmd) {
				int num;
				int pos;
				if (strcmp(folder_name, "0:") == 0) {
					strcpy(Path_folder, folder_name);
				} else if (strcmp(folder_name, "..") == 0) {
					PathGoBack(Path_folder);
				} else if (strcmp(folder_name, ".") == 0) {
				} else {
					strcat(Path_folder, "/");
					strcat(Path_folder, folder_name);
				}
				OUTPUT_USARTTerm;
				printf("folder path to open:%s\r\n", Path_folder);
				ClearVariable(List_file);
				num = ListDir(Path_folder, List_file);
				if (num == -1) {
					PathGoBack(Path_folder);
				}
				OUTPUT_USARTTerm;
				puts("--File List:--\r\n");
				pos = 0;
				while (strlen(List_file[pos].fname) != 0) {
					OUTPUT_USARTTerm;
					flag_export_usart = 1;
					printf(List_file[pos].fname);
					if (CheckIfFile(List_file[pos].fname) == 0) {
						puts(" <F>");
					}
					puts("\r\n");
					flag_export_usart = 0;
					pos++;
				}
				OUTPUT_USARTTerm
				puts("--End of list--\r\n");
				flag_lcd_display = 1;

				flag_browse = 0;
			} else if (CMD_index == file_open_text_cmd) {
				if (CheckIfFile(filename_open) == 1) {
					char data[128];
					unsigned long ofs = 0;
					OUTPUT_USARTTerm;
					printf("filename to open:%s\r\n", filename_open);
					if (flag_open_file == 1) {
						OUTPUT_USARTTerm;
						printf("lcd_menu_index:%u\r\n", lcd_menu_index);
						ClearString(file_content_to_lcd[0]);
						ReadFileText(filename_open, file_content_to_lcd[0], 16,
								lcd_menu_index * 16);
						OUTPUT_USARTTerm;
						printf("file_content_to_lcd[0]:%s\r\n",
								file_content_to_lcd[0]);
						ClearString(file_content_to_lcd[1]);
						ReadFileText(filename_open, file_content_to_lcd[1], 16,
								(lcd_menu_index + 1) * 16);
						OUTPUT_USARTTerm;
						printf("file_content_to_lcd[1]:%s\r\n",
								file_content_to_lcd[1]);
						flag_lcd_display = 1;
					} else {
						OUTPUT_USARTTerm;
						puts("\r\n--Content:--\r\n");
						do {
							ClearString(data);
							ofs = ofs + ReadFileText(filename_open, data, 128,
									ofs);
							OUTPUT_USARTTerm;
							flag_export_usart = 1;
							puts(data);
							flag_export_usart = 0;
						} while (strlen(data) != 0);
						OUTPUT_USARTTerm;
						puts("\r\n--End--\r\n");
					}
					flag_browse = 0;
				} else {
					OUTPUT_USARTTerm;
					printf("%s is NOT a file\r\n", filename_open);
					sprintf(folder_name, "%s", filename_open);
					CMD_index = file_dir_cmd;
				}
			} else if (CMD_index == file_open_wav_cmd) {
				if (CheckIfFile(filename_open) == 1) {
					if (CheckIfWAV(filename_open, &WAV_info_to_read) == 1) {
						if (flag_open_file == 1) {
							LCD_ClearLine(0);
							OUTPUT_LCD;
							printf("%u CH,%u kbps",
									WAV_info_to_read.NumOfChannels,
									WAV_info_to_read.BytePerSec * 8 / 1000);
							LCD_ClearLine(1);
							OUTPUT_LCD;
							printf("%u sample/second",
									WAV_info_to_read.SampleRate);
							DAC1_Configuration();
							DAC1_play_WAV(WAV_info_to_read);
							flag_open_file = 0;
						} else {
							flag_export_usart = 1;
							OUTPUT_USARTTerm;
							printf("Info of file %s:\r\n",
									WAV_info_to_read.Name);
							OUTPUT_USARTTerm;
							printf("%u channels\r\n",
									WAV_info_to_read.NumOfChannels);
							OUTPUT_USARTTerm;
							printf("%u sample/second\r\n",
									WAV_info_to_read.SampleRate);
							OUTPUT_USARTTerm;
							printf("%u kbps\r\n", WAV_info_to_read.BytePerSec
									* 8 / 1000);
							DAC1_Configuration();
							DAC1_play_WAV(WAV_info_to_read);
							flag_export_usart = 0;
						}
						flag_browse = 0;
					} else {
						OUTPUT_USARTTerm;
						printf("%s is NOT a wav file\r\n", filename_open);
						flag_browse = 0;
					}
				} else {
					OUTPUT_USARTTerm;
					printf("%s is NOT a file\r\n", filename_open);
					sprintf(folder_name, "%s", filename_open);
					CMD_index = file_dir_cmd;
				}
			}
		}
		CoLeaveMutexSection(task_browse_sdcard_mutex);
		CoTickDelay(1);
	}
}

/*
 *
 */
void task_keypad(void* pdata) {
	unsigned int kp_code = 0;
	char str_tmp[16];
	while (1) {
		CoEnterMutexSection(task_keypad_mutex);
		//		kp_code = 0;
		//		if(flag_lcd_display == 0)
		//		{
		kp_code = ReadKeypad4x4();
		//		}
		if (kp_code != 0) {
			OUTPUT_USARTTerm;
			printf("kp code: %u\r\n", kp_code);
			if (CMD_index == file_open_wav_cmd) {
				DAC1_stop_WAV(WAV_info_to_read);
				CMD_index = error_cmd;
			}
		}
		if (kp_code == key_menu) {
			lcd_menu_lvl = root_level;
			lcd_menu_index = 0;
			if (Mode_Sel == file_mode) {
				flag_open_file = 0;
				CMD_index = file_dir_cmd;
				strcpy(folder_name, "0:");
				flag_browse = 1;
			}
			flag_lcd_display = 1;
		} else if (kp_code == key_left) {
			if (Mode_Sel == file_mode) {
				strcpy(folder_name, ".");
				CMD_index = file_dir_cmd;
				lcd_menu_index = 0;
				flag_open_file = 1;
				flag_browse = 1;
			}
		} else if (kp_code == key_up) {
			if (lcd_menu_index != 0) {
				lcd_menu_index--;
				if (CMD_index == file_open_text_cmd) {
					flag_browse = 1;
				} else {
					flag_lcd_display = 1;
				}
			}
		} else if (kp_code == key_down) {
			if (Mode_Sel == adc_mode) {
				if (strlen(Menu_adc[lcd_menu_index + 1]) != 0) {
					lcd_menu_index++;
					flag_lcd_display = 1;
				}
			} else if (Mode_Sel == dac_mode) {
				if (strlen(Menu_dac[lcd_menu_index + 1]) != 0) {
					lcd_menu_index++;
					flag_lcd_display = 1;
				}
			} else if (Mode_Sel == led_mode) {
				if (strlen(Menu_led[lcd_menu_index + 1]) != 0) {
					lcd_menu_index++;
					flag_lcd_display = 1;
				}
			} else if (Mode_Sel == file_mode) {
				if (CMD_index == file_dir_cmd) {
					if (strlen(List_file[lcd_menu_index + 1].fname) != 0) {
						lcd_menu_index++;
						flag_lcd_display = 1;
					}
				} else if (CMD_index == file_open_text_cmd) {
					if (strlen(file_content_to_lcd[1]) != 0) {
						lcd_menu_index++;
						flag_browse = 1;
					}
				}
			}
		} else if (kp_code == key_select) {
			if (Mode_Sel == adc_mode) {
				strcpy(str_tmp, Menu_adc[lcd_menu_index]);
				if (strcmp(str_tmp, "ADC read") == 0) {
					CMD_index = adc_read_cmd;
					flag_adc_convert = 1;
				} else if (strcmp(str_tmp, "set alarm min") == 0) {
					CMD_index = adc_set_alarm_min_cmd;
					adc_val = Keypad_Set_Value(0, 99, "%");
					OUTPUT_LCD;
					puts("->set");
					flag_adc_convert = 1;
				} else if (strcmp(str_tmp, "get alarm min") == 0) {
					CMD_index = adc_get_alarm_min_cmd;
					flag_adc_convert = 1;
				} else if (strcmp(str_tmp, "set alarm max") == 0) {
					CMD_index = adc_set_alarm_max_cmd;
					adc_val = Keypad_Set_Value(1, 100, "%");
					OUTPUT_LCD;
					puts("->set");
					flag_adc_convert = 1;
				} else if (strcmp(str_tmp, "get alarm max") == 0) {
					CMD_index = adc_get_alarm_max_cmd;
					flag_adc_convert = 1;
				} else if (strcmp(str_tmp, "active alarm") == 0) {
					CMD_index = adc_act_alarm_cmd;
					adc_val = Keypad_Set_Value(0, 100, "x100ms");
					//LCD_ClearLine(1);
					OUTPUT_LCD;
					if (adc_val == 0) {
						puts("->off");
					} else {
						puts("->active");
					}
					flag_adc_convert = 1;
				}
			} else if (Mode_Sel == dac_mode) {
				strcpy(str_tmp, Menu_dac[lcd_menu_index]);
				if (strcmp(str_tmp, "gen const") == 0) {
					CMD_index = dac_const_cmd;
					dac_valA = Keypad_Set_Value(1, 100, "%VDD");
					OUTPUT_LCD;
					puts("->set");
					flag_dac_gen = 1;
				} else if (strcmp(str_tmp, "gen sine") == 0) {
					CMD_index = dac_sine_cmd;
					dac_valA = Keypad_Set_Value(1, 20000, "Hz");
					OUTPUT_LCD;
					puts("->set");
					flag_dac_gen = 1;
				} else if (strcmp(str_tmp, "gen square") == 0) {
					CMD_index = dac_square_cmd;
					dac_valA = Keypad_Set_Value(1, 20000, "Hz");
					OUTPUT_LCD;
					puts("->set");
					flag_dac_gen = 1;
				} else if (strcmp(str_tmp, "gen triangular") == 0) {
					CMD_index = dac_triangular_cmd;
					dac_valA = Keypad_Set_Value(1, 20000, "Hz");
					OUTPUT_LCD;
					puts("->set");
					flag_dac_gen = 1;
				} else if (strcmp(str_tmp, "gen square custom") == 0) {
					CMD_index = dac_sine_cmd;
					LCD_ClearLine(0);
					OUTPUT_LCD;
					puts("T on:");
					dac_valA = Keypad_Set_Value(100, 2000, "ms");
					LCD_ClearLine(0);
					OUTPUT_LCD;
					puts("T off:");
					dac_valB = Keypad_Set_Value(0, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_dac_gen = 1;
				}
			} else if (Mode_Sel == led_mode) {
				strcpy(str_tmp, Menu_led[lcd_menu_index]);
				if (strcmp(str_tmp, "SHR") == 0) {
					CMD_index = led_shr_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "SHL") == 0) {
					CMD_index = led_shl_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "Inc L->R") == 0) {
					CMD_index = led_inc_lr_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "Inc R->L") == 0) {
					CMD_index = led_inc_rl_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "Dec L->R") == 0) {
					CMD_index = led_dec_lr_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "Dec R->L") == 0) {
					CMD_index = led_dec_rl_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "IncDec L->R") == 0) {
					CMD_index = led_incdec_lr_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				} else if (strcmp(str_tmp, "IncDec R->L") == 0) {
					CMD_index = led_incdec_rl_cmd;
					led_delay = Keypad_Set_Value(100, 2000, "ms");
					OUTPUT_LCD;
					puts("->set");
					flag_led_blinky = 1;
				}
			} else if (Mode_Sel == file_mode) {
				char fake_CMD[] = "CMD_file_open_";
				strcat(fake_CMD, filename_open);
				CMD_index = ParseCMD_filemode(fake_CMD);
				OUTPUT_USARTTerm;
				printf("CMD_index: %d\r\n", CMD_index);
				if (CMD_index == file_dir_cmd) {
					strcpy(folder_name, fake_CMD);
					OUTPUT_USARTTerm;
					printf("open folder %s\r\n", folder_name);
					lcd_menu_index = 0;
					flag_open_file = 1;
					flag_browse = 1;
				} else if (CMD_index == file_open_text_cmd) {
					strcpy(filename_open, fake_CMD);
					OUTPUT_USARTTerm;
					printf("open text file %s\r\n", filename_open);
					lcd_menu_index = 0;
					flag_open_file = 1;
					flag_browse = 1;
				} else if (CMD_index == file_open_mp3_cmd) {
					strcpy(filename_open, fake_CMD);
					OUTPUT_USARTTerm;
					printf("open mp3 file %s\r\n", filename_open);
					lcd_menu_index = 0;
					flag_open_file = 1;
					flag_browse = 1;
				} else if (CMD_index == file_open_wav_cmd) {
					strcpy(filename_open, fake_CMD);
					OUTPUT_USARTTerm;
					printf("open wav file %s\r\n", filename_open);
					lcd_menu_index = 0;
					flag_open_file = 1;
					flag_browse = 1;
				}
				//				lcd_menu_index = 0;
				//				flag_open_file = 1;
				//				flag_browse = 1;
			}
		}
		CoLeaveMutexSection(task_keypad_mutex);
		CoTickDelay(50);
	}
}

/****************************************************************
 * task to get a string via usart Term
 * parse and identify this string
 *
 ****************************************************************/
void task_get_usartTerm(void* pdata) {
	char str_recv[100];
	unsigned int flag_get_all = 0;
	unsigned long ofs = 0;
	char str_tmp[512] = "";
	while (1) {
		CoEnterMutexSection(task_get_usartTerm_mutex);
		do {
			CoTickDelay(1);
			ClearString(str_recv);
			uGets(str_recv,flag_get_all);
		} while (strcmp(str_recv, "") == 0);
		OUTPUT_USARTTerm;
		printf("String got: %s\r\n", str_recv);
		if (CMD_index == file_create_cmd) {
			strcat(data_write,str_recv);



			if (FindInString(str_tmp, "<EXIT>") != -1) {
				OUTPUT_USARTTerm;
				puts("start write\r\n");
				ofs = ofs + WriteFile(filename_open, str_tmp, ofs);
				OUTPUT_USARTTerm;
				puts("write done\r\n");
				CMD_index = error_cmd;
				ofs = 0;
				strcpy(str_tmp,"");
				flag_get_all = 0;
			} else {
				strcat(str_tmp,str_recv);
				OUTPUT_USARTTerm;
				printf("str_tmp: %s\r\n", str_tmp);
				if(strlen(str_tmp) >= 386)
				{
					ofs = ofs + WriteFile(filename_open, str_tmp, ofs);
				}
			} else if (CMD_index == file_stop_wav_cmd) {
				OUTPUT_USARTTerm;
				puts("stop playing WAV file\r\n");
				DAC1_stop_WAV(WAV_info_to_read);
			}
		} else {
			if (Mode_Sel == file_mode) {
				StringCut(str_recv, " <F>");
				CMD_index = ParseCMD_filemode(str_recv);
				OUTPUT_USARTTerm;
				printf("CMD_index: %d\r\n", CMD_index);
				if (CMD_index == file_dir_cmd) {
					strcpy(folder_name, str_recv);
					OUTPUT_USARTTerm;
					printf("open folder %s\r\n", folder_name);
					flag_browse = 1;
				} else if (CMD_index == file_create_cmd) {
					strcpy(filename_open, str_recv);
					OUTPUT_USARTTerm;
					printf("Create file %s\r\n", filename_open);
					CreateFile(filename_open);
					flag_get_all = 1;
				} else if (CMD_index == file_open_text_cmd) {
					strcpy(filename_open, str_recv);
					OUTPUT_USARTTerm;
					printf("open text file %s\r\n", filename_open);
					flag_browse = 1;
				} else if (CMD_index == file_open_mp3_cmd) {
					strcpy(filename_open, str_recv);
					OUTPUT_USARTTerm;
					printf("open mp3 file %s\r\n", filename_open);
					flag_browse = 1;
				} else if (CMD_index == file_open_wav_cmd) {
					strcpy(filename_open, str_recv);
					OUTPUT_USARTTerm;
					printf("open wav file %s\r\n", filename_open);
					flag_browse = 1;
				}
			} else if (Mode_Sel == dac_mode) {
				dac_valA = 0;
				dac_valB = 0;
				CMD_index = ParseCMD_dacmode(str_recv, &dac_valA, &dac_valB);
				if (CMD_index == dac_const_cmd) {
					OUTPUT_USARTTerm;
					printf("generate constant DAC signal: %u %% of VDD\r\n",
							dac_valA);
					flag_dac_gen = 1;
				} else if (CMD_index == dac_sine_cmd) {
					OUTPUT_USARTTerm;
					printf("generate sine DAC signal: %u Hz\r\n", dac_valA);
					flag_dac_gen = 1;
				} else if (CMD_index == dac_square_cmd) {
					OUTPUT_USARTTerm;
					printf("generate square DAC signal: %u Hz\r\n", dac_valA);
					flag_dac_gen = 1;
				} else if (CMD_index == dac_triangular_cmd) {
					OUTPUT_USARTTerm;
					printf("generate triangular DAC signal: %u Hz\r\n",
							dac_valA);
					flag_dac_gen = 1;
				} else if (CMD_index == dac_squarecustom_cmd) {
					OUTPUT_USARTTerm;
					puts("generate custom square DAC signal: ");
					printf("T_on = %u s, T_off = %u ms\r\n", dac_valA, dac_valB);
					flag_dac_gen = 1;
				}
			} else if (Mode_Sel == adc_mode) {
				adc_val = 0;
				CMD_index = ParseCMD_adcmode(str_recv, &adc_val);
				if (CMD_index == adc_read_cmd) {
					OUTPUT_USARTTerm;
					puts("Read out converted result of ADC\r\n");
					flag_adc_convert = 1;
				} else if (CMD_index == adc_set_alarm_max_cmd) {
					OUTPUT_USARTTerm;
					printf("set ADC alarm high level: %u %% of VDD\r\n",
							adc_val);
					flag_adc_convert = 1;
				} else if (CMD_index == adc_set_alarm_min_cmd) {
					OUTPUT_USARTTerm;
					printf("set ADC alarm low level: %u %% of VDD\r\n", adc_val);
					flag_adc_convert = 1;
				} else if (CMD_index == adc_get_alarm_max_cmd) {
					OUTPUT_USARTTerm;
					puts("get ADC alarm high level\r\n");
					flag_adc_convert = 1;
				} else if (CMD_index == adc_get_alarm_min_cmd) {
					OUTPUT_USARTTerm;
					puts("get ADC alarm low level\r\n");
					flag_adc_convert = 1;
				} else if (CMD_index == adc_act_alarm_cmd) {
					OUTPUT_USARTTerm;
					printf("Active ADC alarm with delay %u x 100ms\r\n",
							adc_val);
					flag_adc_convert = 1;
				}
			} else if (Mode_Sel == led_mode) {
				led_delay = 0;
				CMD_index = ParseCMD_ledmode(str_recv, &led_delay);
				if (CMD_index == led_shr_cmd) {
					OUTPUT_USARTTerm;
					printf("LED shift right: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_shl_cmd) {
					OUTPUT_USARTTerm;
					printf("LED shift left: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_inc_lr_cmd) {
					OUTPUT_USARTTerm;
					printf("LED increase left to right: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_inc_rl_cmd) {
					OUTPUT_USARTTerm;
					printf("LED increase right to left: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_dec_lr_cmd) {
					OUTPUT_USARTTerm;
					printf("LED decrease left to right: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_dec_rl_cmd) {
					OUTPUT_USARTTerm;
					printf("LED decrease right to left: %u ms\r\n", led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_incdec_lr_cmd) {
					OUTPUT_USARTTerm;
					printf(
							"LED increase and decrease left to right: %u ms\r\n",
							led_delay);
					flag_led_blinky = 1;
				} else if (CMD_index == led_incdec_rl_cmd) {
					OUTPUT_USARTTerm;
					printf(
							"LED increase and decrease right to left: %u ms\r\n",
							led_delay);
					flag_led_blinky = 1;
				}
			}
		}
		CoLeaveMutexSection(task_get_usartTerm_mutex);
		CoTickDelay(1);
	}
}

/****************************************************************
 * just make a led flash, tell user that program is running
 *
 ****************************************************************/
void task_led_blinky(void* pdata) {
	LED_configuration();
	OUTPUT_USARTTerm;
	puts("LED_configuration\r\n");
	timer_LED_config();
	OUTPUT_USARTTerm;
	puts("timer_LED_config\r\n");
	while (1) {
		CoEnterMutexSection(task_led_blinky_mutex);
		if (flag_led_blinky == 1) {
			if (CMD_index == led_shr_cmd) {
				LED_active(led_shr, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_shl_cmd) {
				LED_active(led_shl, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_inc_lr_cmd) {
				LED_active(led_inc_lr, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_inc_rl_cmd) {
				LED_active(led_inc_rl, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_dec_lr_cmd) {
				LED_active(led_dec_lr, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_dec_rl_cmd) {
				LED_active(led_dec_rl, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_incdec_lr_cmd) {
				LED_active(led_incdec_lr, led_delay);
				flag_led_blinky = 0;
			} else if (CMD_index == led_incdec_rl_cmd) {
				LED_active(led_incdec_rl, led_delay);
				flag_led_blinky = 0;
			}
		}
		CoLeaveMutexSection(task_led_blinky_mutex);
		CoTickDelay(1);
	}
}
//-------------------------------------------------------------
unsigned int Keypad_Set_Value(unsigned int Min, unsigned int Max, char *unit) {
	unsigned int value_tmp = Min;
	unsigned int kp_code = 0;
	LCD_ClearLine(1);
	OUTPUT_LCD;
	printf("%u %s", value_tmp, unit);
	while (1) {
		kp_code = ReadKeypad4x4();
		if (kp_code == key_select) {
			return value_tmp;
		} else if (kp_code == key_up) {
			if (value_tmp < Max) {
				value_tmp++;
			}
			LCD_ClearLine(1);
			OUTPUT_LCD;
			printf("%u %s", value_tmp, unit);
		} else if (kp_code == key_down) {
			if (value_tmp > Min) {
				value_tmp--;
			}
			LCD_ClearLine(1);
			OUTPUT_LCD;
			printf("%u %s", value_tmp, unit);
		}
		CoTickDelay(1);
	}
}
//-------------------------------------------------------------
int main(void) {
	SystemInit();
	//set value for global variable
	FLAG_CONNECT_TYPE = CONNECT_TERMINAL;
	strcpy(folder_name, "0:");
	General_Config();
	flag_export_usart = 0;
	lcd_current_line = 0;
	Mode_Sel = 0;
	USARTTermInit();
	LCD_Init();
	SwitchTIM2IRQ(DISABLE);
	SwitchUSART1IRQ(ENABLE);
	ModeSel_Configuration();
	timer_Keypad_config();
	Keypad4x4Config();
	Switch_timer_Keypad_IRQ(ENABLE);
	Mode_Sel = ModeSel();
	OUTPUT_USARTTerm;
	printf("mode index = %u\r\n", Mode_Sel);
	char str_tmp[20];
	while (1) {
		delayms(50);
		ClearString(str_tmp);
		uGets(str_tmp,0);
		if (FindInString(str_tmp, "CONNECT_SOFTWARE") != -1) {
			OUTPUT_LCD;
			puts("CONNECT SOFTWARE");
			FLAG_CONNECT_TYPE = CONNECT_SOFTWARE;
			Switch_timer_Keypad_IRQ(DISABLE);
			break;
		} else if (FindInString(str_tmp, "CONNECT_TERMINAL") != -1) {
			OUTPUT_LCD;
			puts("CONNECT TERMINAL");
			FLAG_CONNECT_TYPE = CONNECT_TERMINAL;
			Switch_timer_Keypad_IRQ(DISABLE);
			break;
		} else {
			if (ReadKeypad4x4() != 0) {
				OUTPUT_LCD;
				puts("CONNECT KEYPAD");
				FLAG_CONNECT_TYPE = CONNECT_KEYPAD;
				break;
			}
		}
	}
	OUTPUT_USARTTerm;
	puts("\r\n");
	puts(" ----------------------------------------------------------  \r\n");
	puts("|  ___   ___   ______   ___      ___      _________   ___  ||\r\n");
	puts("| |  || |  || |   __|| |  ||    |  ||    |   __   || |  || ||\r\n");
	puts("| |  ||_|  || |  ||__  |  ||    |  ||    |  || |  || |  || ||\r\n");
	puts("| |   __   || |   __|| |  ||    |  ||    |  || |  || |  || ||\r\n");
	puts("| |  || |  || |  ||__  |  ||__  |  ||__  |  ||_|  || |__|| ||\r\n");
	puts("| |__|| |__|| |_____|| |_____|| |_____|| |________||  []]  ||\r\n");
	puts("|                                                          ||\r\n");
	puts(" ----------------------------------------------------------  \r\n");
	LCD_ClearLine(1);
	OUTPUT_LCD;
	switch (Mode_Sel) {
	case file_mode:
		puts("file mode");
		break;
	case dac_mode:
		puts("DAC mode");
		break;
	case adc_mode:
		puts("ADC mode");
		break;
	case led_mode:
		puts("LED mode");
		break;
	default:
		puts("file mode");
		break;
	}
	OUTPUT_USARTTerm;
	//-------------------------------------------------------------------------
	if (Mode_Sel == file_mode) {
		puts("Search SD card... ");
		while (MountingSDcard() == 0) {
			delays(1);
			puts("\r\n--- Please Insert SD Card ---\r\n");
		}
		puts("[DONE]\r\n");
	}
	//-------------------------------------------------------------------------
	puts("Initialize OS... ");
	CoInitOS();
	puts("[DONE]\r\n");
	//-------------------------------------------------------------------------
	puts("Create task...\r\n");
	if ((FLAG_CONNECT_TYPE == CONNECT_SOFTWARE) || (FLAG_CONNECT_TYPE
			== CONNECT_TERMINAL)) {
		puts("\ttask_get_usartTerm... ");
		task_get_usartTerm_id = create_task_get_usartTerm;
		if (task_get_usartTerm_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (FLAG_CONNECT_TYPE == CONNECT_KEYPAD) {
		puts("\ttask_keypad... ");
		task_keypad_id = create_task_keypad;
		if (task_keypad_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
		puts("\ttask_lcd_menu... ");
		task_lcd_menu_id = create_task_lcd_menu;
		if (task_lcd_menu_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	}
	if (Mode_Sel == file_mode) {
		puts("\ttask_browse_sdcard... ");
		task_browse_sdcard_id = create_task_browse_sdcard;
		if (task_browse_sdcard_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
		puts("\ttask_write_sdcard... ");
		task_write_sdcard_id = create_task_write_sdcard;
		if (task_write_sdcard_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == dac_mode) {
		puts("\ttask_generate_dac... ");
		task_generate_dac_id = create_task_generate_dac;
		if (task_generate_dac_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == adc_mode) {
		puts("\ttask_adc_convert... ");
		task_adc_convert_id = create_task_adc_convert;
		if (task_adc_convert_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == led_mode) {
		puts("\ttask_led_blinky... ");
		task_led_blinky_id = create_task_led_blinky;
		if (task_led_blinky_id != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	}
	//-------------------------------------------------------------------------
	puts("Create mutexes...\r\n");
	if ((FLAG_CONNECT_TYPE == CONNECT_SOFTWARE) || (FLAG_CONNECT_TYPE
			== CONNECT_TERMINAL)) {
		puts("\ttask_get_usartTerm_mutex...");
		task_get_usartTerm_mutex = CoCreateMutex();
		if (task_get_usartTerm_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (FLAG_CONNECT_TYPE == CONNECT_KEYPAD) {
		puts("\ttask_keypad_mutex...");
		task_keypad_mutex = CoCreateMutex();
		if (task_keypad_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
		puts("\ttask_lcd_menu_mutex...");
		task_lcd_menu_mutex = CoCreateMutex();
		if (task_lcd_menu_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	}

	if (Mode_Sel == file_mode) {
		puts("\ttask_browse_sdcard_mutex... ");
		task_browse_sdcard_mutex = CoCreateMutex();
		if (task_browse_sdcard_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
		puts("\ttask_write_sdcard_mutex...");
		task_write_sdcard_mutex = CoCreateMutex();
		if (task_write_sdcard_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == dac_mode) {
		puts("\ttask_generate_dac_mutex...");
		task_generate_dac_mutex = CoCreateMutex();
		if (task_generate_dac_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == adc_mode) {
		puts("\ttask_adc_convert_mutex...");
		task_adc_convert_mutex = CoCreateMutex();
		if (task_adc_convert_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	} else if (Mode_Sel == led_mode) {
		puts("\ttask_led_blinky_mutex...");
		task_led_blinky_mutex = CoCreateMutex();
		if (task_led_blinky_mutex != E_CREATE_FAIL) {
			puts("[DONE]\r\n");
		} else {
			puts("[FAIL]\r\n");
			while (1)
				;
		}
	}
	//-------------------------------------------------------------------------
	puts("Start OS\r\n");
	OUTPUT_LCD;
	puts("- START");
	CoStartOS();
	//		WAV_INFO wav_if;
	//		CheckIfWAV("test.wav",&wav_if);
	//		OUTPUT_USARTTerm;
	//		printf("byte per sample:%u\r\n",wav_if.BytePerSample);
	//		DAC1_Configuration();
	//		DAC1_play_WAV(wav_if);
	while (1) {
		//		OUTPUT_USARTTerm;
		//		puts("tick\r\n");
		//		delayms(1000);
	}
}
